package sv.gob.mh.dgii.model.pojos.ruc;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.Transient;

import sv.gob.mh.dgii.common.Utils;
import sv.gob.mh.dgii.model.RcActEco;
import sv.gob.mh.dgii.model.RcDocIdentidad;
import sv.gob.mh.dgii.model.RcDomicilio;
import sv.gob.mh.dgii.model.RcRepresentante;
import sv.gob.mh.dgii.model.RcSocio;
import sv.gob.mh.dgii.model.RcSocioId;
import sv.gob.mh.dgii.model.TbActEco;
import sv.gob.mh.dgii.model.TbClaseContrib;
import sv.gob.mh.dgii.model.TbMunicipio;
import sv.gob.mh.dgii.model.TbPais;
import sv.gob.mh.dgii.model.TbTipoContrib;

public class F210 implements Serializable {

	private static final long serialVersionUID = 1L;

        //A
	private String nit;
	private String s1apeRasoc;
        private String s2apeAbrev;
        private String snombres;
        private String msexo;
        private TbClaseContrib tbClaseContrib;
        private TbTipoContrib tbTipoContrib;                
        private String nomComercial;
        
        //B
        private TbPais tbPais;
        private boolean domiciliado;
        private TbMunicipio tbMunicipio;
	private Date fnacConst;
	private BigDecimal capital;
        private boolean importador;
	private RcDocIdentidad rcDocIdentidad;
        
        //C
	private RcDomicilio domicilioNotificacion;
        private Domicilio domicilioEnEdicion = new Domicilio();
        
        //D
	private RcDomicilio domicilioCasaMatriz;
        private Domicilio casaMatrizEnEdicion = new Domicilio();
        
        //H
	private List<RcDomicilio> domicilios;//seccion H, predios, sucursales
        
        //E
	private List<RcActEco> actividadesEconomicas;
        private HashMap<String,TbActEco> actividadesEnEdicion;
        
        //F
	private List<RcRepresentante> representantes;
        private HashMap<String,RcRepresentante> representantesEnEdicion;
        
	private List<RcSocio> socios;//I
	
	//Indica aquellas secciones que este contribuyente tiene permitido editar.
	private List<Seccion> secciones = new ArrayList<Seccion>();
	private String tramites;
        
        private HashMap<String,Object> old_values = new HashMap<String, Object>();
        
	//Hash para identificar el query de busqueda usado para construir
        //este objeto, presente y util solo
        private String hash;
        
        
	public String getS1apeRasoc() {
		return s1apeRasoc;
	}
	public void setS1apeRasoc(String s1apeRasoc) {
		this.s1apeRasoc = s1apeRasoc;
	}
	public String getS2apeAbrev() {
		return s2apeAbrev;
	}
	public void setS2apeAbrev(String s2apeAbrev) {
		this.s2apeAbrev = s2apeAbrev;
	}
	public String getSnombres() {
		return snombres;
	}
	public void setSnombres(String snombres) {
		this.snombres = snombres;
	}
	public String getMsexo() {
		return msexo;
	}
	public void setMsexo(String msexo) {
		this.msexo = msexo;
	}
	public TbClaseContrib getTbClaseContrib() {
		return tbClaseContrib;
	}
	public void setTbClaseContrib(TbClaseContrib tbClaseContrib) {
		this.tbClaseContrib = tbClaseContrib;
	}
	public TbTipoContrib getTbTipoContrib() {
		return tbTipoContrib;
	}
	public void setTbTipoContrib(TbTipoContrib tbTipoContrib) {
		this.tbTipoContrib = tbTipoContrib;
	}
	public boolean isImportador() {
		return importador;
	}
	public void setImportador(boolean importador) {
		this.importador = importador;
	}
	public boolean isDomiciliado() {
		return domiciliado;
	}
	public void setDomiciliado(boolean domiciliado) {
		this.domiciliado = domiciliado;
	}
	public Date getFnacConst() {
		return fnacConst;
	}
	public void setFnacConst(Date fnacConst) {
		this.fnacConst = fnacConst;
	}
	public RcDocIdentidad getRcDocIdentidad() {
		return rcDocIdentidad;
	}
	public void setRcDocIdentidad(RcDocIdentidad rcDocIdentidad) {
		this.rcDocIdentidad = rcDocIdentidad;
	}
	public BigDecimal getCapital() {
		return capital;
	}
	public void setCapital(BigDecimal capital) {
		this.capital = capital;
	}

	public String getNomComercial() {
		return nomComercial;
	}
	public void setNomComercial(String nomComercial) {
		this.nomComercial = nomComercial;
	}
	
	public String getNit() {
		return nit;
	}
	public void setNit(String nit) {
		this.nit = nit;
	}
	public TbMunicipio getTbMunicipio() {
		return tbMunicipio;
	}
	public void setTbMunicipio(TbMunicipio tbMunicipio) {
		this.tbMunicipio = tbMunicipio;
	}
	public TbPais getTbPais() {
		return tbPais;
	}
	public void setTbPais(TbPais tbPais) {
		this.tbPais = tbPais;
	}
		
	public RcDomicilio getDomicilioNotificacion() {
		return domicilioNotificacion;
	}
	public void setDomicilioNotificacion(RcDomicilio domicilioNotificacion) {
		this.domicilioNotificacion = domicilioNotificacion;
	}

	public RcDomicilio getDomicilioCasaMatriz() {
		return domicilioCasaMatriz;
	}
	public void setDomicilioCasaMatriz(RcDomicilio domicilioCasaMatriz) {
		this.domicilioCasaMatriz = domicilioCasaMatriz;
	}	
	public List<RcDomicilio> getDomicilios() {
		return domicilios;
	}
	public void setDomicilios(List<RcDomicilio> domicilios) {
		this.domicilios = domicilios;
	}

	public List<RcActEco> getActividadesEconomicas() {
		return actividadesEconomicas;
	}
	public void setActividadesEconomicas(List<RcActEco> actividadesEconomicas) {
		this.actividadesEconomicas = actividadesEconomicas;
	}
	public List<RcRepresentante> getRepresentantes() {
		return representantes;
	}
	public void setRepresentantes(List<RcRepresentante> representantes) {
		this.representantes = representantes;
	}
	public List<RcSocio> getSocios() {
		return socios;
	}
	public void setSocios(List<RcSocio> socios) {
		this.socios = socios;
	}

	public List<Seccion> getSecciones() {
		return secciones;
	}
	public void setSecciones(List<Seccion> secciones) {
		this.secciones = secciones;
	}
	public String getTramites() {
		return tramites;
	}
	public void setTramites(String tramites) {
		this.tramites = tramites;
	}
        
        /**
        * @return the old_values
        */
       public HashMap<String,Object> getOld_values() {
           return old_values;
       }

       /**
        * @param old_values the old_values to set
        */
       public void setOld_values(HashMap<String,Object> old_values) {
           this.old_values = old_values;
       }
       
       
       
       //posibles tipos de datos a comparar, string, object, bigdecimal
       public void put_new_value(String key, Object value){
            try {
                Field field = this.getClass().getDeclaredField(key);
                Object old_value = field.get(this);                
                if(!Utils.isNullOrEmpty(old_value) &&
                   !Utils.isNullOrEmpty(value) &&
                   !old_value.equals(value)){ //ojo con los objetos hay que escribir un correcto metodo equals
                   field.set(this, value);
                   // System.out.println("Distintos valores " + key + " " + old_value);
                    //System.out.println("Distintos valores " + key + " " + value);
                   if(!this.old_values.containsKey(key)){
                       this.old_values.put(key, old_value);
                   }
                }/*else{
                    System.out.println("mismo valor");
                }*/
                
                //Si el valor viejo es null, en el caso de la inscripcion trae
                //ciertos valores nulos al iniciar
                if(Utils.isNullOrEmpty(old_value) && !Utils.isNullOrEmpty(value)){
                   field.set(this, value);
                   if(!this.old_values.containsKey(key)){
                       this.old_values.put(key, old_value);
                   }
                }
            } catch (Exception ex) {
                //ignored, simplemente no se copia el valor
                ex.printStackTrace();
            }
       }
             
       public void put_new_values_A(A a){           
           put_new_value("s1apeRasoc", a.getS1apeRasoc());
           put_new_value("s2apeAbrev", a.getS2apeAbrev());
           put_new_value("msexo", a.getMsexo());
           put_new_value("snombres", a.getSnombres());
           put_new_value("tbTipoContrib", a.getTbTipoContrib());
           put_new_value("nomComercial", a.getNomComercial());                
       }
       
       public void put_new_values_B(B b){           
           put_new_value("rcDocIdentidad", b.getRcDocIdentidad());
           put_new_value("importador", b.isImportador());
           put_new_value("capital", b.getCapitalSocial());
       }
       
       public void put_new_values_C(C c){           
           put_new_value("domicilioEnEdicion", c.getDomicilio());
           this.old_values.put("domicilioNotificacion", this.domicilioNotificacion);
       }
       
       public void put_new_values_D(D d){
           put_new_value("casaMatrizEnEdicion", d.getDomicilio());
           this.old_values.put("domicilioCasaMatriz", this.domicilioCasaMatriz);
       }
       
       public void finalizarRestaurarRepresentante(Long id,boolean finalizar){
           for (Iterator<RcRepresentante> it = representantes.iterator(); it.hasNext(); ) {
            RcRepresentante rep = it.next();
            if(rep.getIrcRepresentante().compareTo(id)==0){
                   if(finalizar){
                       if(Utils.isNullOrEmpty(rep.getFhingreso())){
                           it.remove();
                       }else{
                           rep.setFfrepresentante(new Date());
                       }                       
                   }else{
                       rep.setFfrepresentante(null);
                   }
               }
            }           
       }
       
        public void finalizarRestaurarSocio(String id,boolean finalizar){
           for (Iterator<RcSocio> it = socios.iterator(); it.hasNext(); ) {
            RcSocio s = it.next();
            if(s.getId().toString().equals(id)){
                   if(finalizar){
                       if(Utils.isNullOrEmpty(s.getFhingreso())){
                           it.remove();
                       }else{
                           s.setFfsocio(new Date());
                       }                       
                   }else{
                       s.setFfsocio(null);
                   }
               }
            }           
       }
        
       public void finalizarRestaurarDomicilio(Long id,boolean finalizar){
           for (Iterator<RcDomicilio> it = domicilios.iterator(); it.hasNext(); ) {
            RcDomicilio dom = it.next();
            if(dom.getIrcDomicilio().compareTo(id)==0){
                   if(finalizar){
                       //Aquellos con fi nula son los nuevos a esos los elimino de
                       //la lista, los que ya existen solo les doy fecha fin.
                       if(Utils.isNullOrEmpty(dom.getFidomicilio())){
                           it.remove();
                       }else{
                           dom.setFfdomicilio(new Date());
                       }                       
                   }else{
                       dom.setFfdomicilio(null);
                   }
               }
            }           
       }
       
       public void finalizarRestaurarActividadEconomica(Long id,boolean finalizar){
           //Finalizo o restauro la actividad
            for (RcActEco act : actividadesEconomicas) {
                if(act.getIrcActEco().compareTo(id)==0){
                    if(finalizar){
                        act.setFfactEco(new Date());
                    }else{
                        if(act.getTbActEco().getBstatus()){//Aquellas actividades deshabilitadas no pueden restaurarse
                            if(act.getOrden().compareTo(1L)==0
                               && actividadesEnEdicion.containsKey("1")){
                                getActividadesEnEdicion().remove("1");
                            }
                            if(act.getOrden().compareTo(2L)==0
                               && actividadesEnEdicion.containsKey("2")){
                                getActividadesEnEdicion().remove("2");
                            }
                            if(act.getOrden().compareTo(3L)==0
                               && actividadesEnEdicion.containsKey("3")){
                                getActividadesEnEdicion().remove("3");
                            }
                            act.setFfactEco(null);
                        }                    
                    }
                }
            }
       }
       
       public void put_new_values_F(F f){
           RcRepresentante rep = new RcRepresentante();
           rep.setCdocAcredita(f.getTipoDocAcredita().getCdocIdentidad());
           rep.setCdocIdentidad(f.getTipoDocIdentidad().getCdocIdentidad());
           rep.setNdocAcredita(f.getNumeroDocAcredita());
           rep.setNdocIdentidad(f.getNumeroDocIdentidad());
           rep.setTbRepresentante(f.getTbRepresentante());           
           rep.setRcRucByNitRepresentante(f.getRcRuc());
           //rep.setFhingreso(new Date());
           rep.setFirepresentante(new Date());
           String pseudoId = f.getTbRepresentante().getCrepresentante()+f.getNit();
           rep.setIrcRepresentante(new Random().nextLong() * -1);
           representantes.add(rep);
       }
       
       public void put_new_values_I(I i){
           RcSocio socio = new RcSocio();
           RcSocioId id = new RcSocioId();
           id.setNit(i.getNit());
           id.setNitsocio(i.getNitsocio());
           id.setFaparticipacion(i.getPorcentage().toString());
           socio.setId(id);
           socio.setFisocio(new Date());
           socio.setVporcPart(i.getPorcentage().doubleValue());
           socio.setRcRucByNitSocio(i.getRcRuc());
           socios.add(socio);
       }
       
       public void put_new_values_H(H h){
           domicilios.add(h.getDomicilio().toRcDomicilio());           
       }
       
       public void put_new_values_E(E e){
           if(Utils.isNullOrEmpty(e.getPrimaria())){
               getActividadesEnEdicion().remove("1");
           }else{
               getActividadesEnEdicion().put("1", e.getPrimaria());
           }
           if(Utils.isNullOrEmpty(e.getSecundaria())){
               getActividadesEnEdicion().remove("2");
           }else{               
               getActividadesEnEdicion().put("2", e.getSecundaria());
           }
           if(Utils.isNullOrEmpty(e.getTerciaria())){
               getActividadesEnEdicion().remove("3");
           }else{
               getActividadesEnEdicion().put("3", e.getTerciaria());
           }
//           for (RcActEco act : actividadesEconomicas) {
//               if(act.getOrden().compareTo(1L)==0){
//                  if(!Utils.isNullOrEmpty(e.getPrimaria())){
//                      act.setFfactEco(new Date());
//                  }else{
//                      act.setFfactEco(null);
//                  }
//               }
//               
//               if(act.getOrden().compareTo(2L)==0){
//                  if(!Utils.isNullOrEmpty(e.getSecundaria())){
//                      act.setFfactEco(new Date());
//                  }else{
//                      act.setFfactEco(null);
//                  }
//               }
//               
//               if(act.getOrden().compareTo(3L)==0){
//                  if(!Utils.isNullOrEmpty(e.getTerciaria())){
//                      act.setFfactEco(new Date());
//                  }else{
//                      act.setFfactEco(null);
//                  }
//               }               
//           }
           
           
       }
       
       //¿Existe un tramite de reposicion de NRC en curso?
       public boolean getReposicion_nrc(){
           if(Utils.isNullOrEmpty(tramites))return false;
           return tramites.charAt(4) == '1';
       }
       public boolean getReposicion_nit(){
           if(Utils.isNullOrEmpty(tramites))return false;
           return tramites.charAt(5) == '1';
       }
       public boolean getModificacion_nit(){
           if(Utils.isNullOrEmpty(tramites))return false;
           return tramites.charAt(6) == '1';
       }
       public boolean getInscripcion_nrc(){
           if(Utils.isNullOrEmpty(tramites))return false;
           return tramites.charAt(3) == '1';
       }
       
       public boolean isNatural(){
           return this.tbClaseContrib.getCclase().equals("N");
       }
        
       public void buildSecciones() {		
		this.secciones.clear();
		this.secciones.add(Seccion.A);
		this.secciones.add(Seccion.B);
		this.secciones.add(Seccion.C);
		this.secciones.add(Seccion.E);
		this.secciones.add(Seccion.F);
		
		if(this.tbClaseContrib.getCclase().equals("J")) {
			this.secciones.add(Seccion.D);			
			this.secciones.add(Seccion.H);
			this.secciones.add(Seccion.I);
		}else {
			//Si es natural y tiene algun tramite de nrc aplica las otras secciones
                        if(!Utils.isNullOrEmpty(tramites)){
                            if(tramites.charAt(3)=='1' || tramites.charAt(4) == '1') {
				this.secciones.add(Seccion.D);			
				this.secciones.add(Seccion.H);
                            }
                        }			
		}
		Collections.sort(this.secciones);
	}
	
	public String getNombreCompleto(){		
		if (!Utils.isNullOrEmpty(this.tbTipoContrib )){		
			if (getTbTipoContrib().getId().getCclase().equals("J")){
				return "" 	+ " " + Utils.nvl(getS1apeRasoc(), "");				
			}
			else {
				return "" 	+ " " + Utils.nvl(getSnombres(), "") 
						+ " " + Utils.nvl(getS1apeRasoc(), "") 
						+ " " + Utils.nvl(getS2apeAbrev(), "");
			}
		}else{
			return "" 	+ " " + Utils.nvl(getSnombres(), "") 
			+ " " + Utils.nvl(getS1apeRasoc(), "") 
			+ " " + Utils.nvl(getS2apeAbrev(), "");
		}
	}
    
    
    public String getNitGuiones(){	
		return Utils.MaskedNit(this.nit);		
    }
    
    public String[] getIdActividadesActuales(){
        ArrayList<String> tbActs = new ArrayList<String>();
        for (RcActEco act : actividadesEconomicas) {
            if(!Utils.isNullOrEmpty(act.getTbActEco().getCactEco())){
                tbActs.add(act.getTbActEco().getCactEco());
            }            
        }        
        return tbActs.toArray(new String[tbActs.size()]);
    }
    
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("F210 [s1apeRasoc=");
		builder.append(s1apeRasoc);
		builder.append(", s2apeAbrev=");
		builder.append(s2apeAbrev);
		builder.append(", snombres=");
		builder.append(snombres);
		builder.append(", msexo=");
		builder.append(msexo);
		builder.append(", tbClaseContrib=");
		builder.append(tbClaseContrib);
		builder.append(", tbTipoContrib=");
		builder.append(tbTipoContrib);
		builder.append(", nomComercial=");
		builder.append(nomComercial);
		builder.append(", importador=");
		builder.append(importador);
		builder.append(", domiciliado=");
		builder.append(domiciliado);
		builder.append(", fnacConst=");
		builder.append(fnacConst);
		builder.append(", capital=");
		builder.append(capital);
		builder.append(", tbMunicipio=");
		builder.append(tbMunicipio);
		builder.append(", tbPais=");
		builder.append(tbPais);
		builder.append(", rcDocIdentidad=");
		builder.append(rcDocIdentidad);
		builder.append(", domicilioNotificacion=");
		builder.append(domicilioNotificacion);
		builder.append(", domicilioCasaMatriz=");
		builder.append(domicilioCasaMatriz);
		builder.append(", domicilios=");
		builder.append(domicilios);
		builder.append(", actividadesEconomicas=");
		builder.append(actividadesEconomicas);
		builder.append(", representantes=");
		builder.append(representantes);
		builder.append(", socios=");
		builder.append(socios);
		builder.append(", secciones=");
		builder.append(secciones);
		builder.append(", tramites=");
		builder.append(tramites);
		builder.append("]");
		return builder.toString();
	}

    /**
     * @return the domicilioEnEdicion
     */
    public Domicilio getDomicilioEnEdicion() {
        return domicilioEnEdicion;
    }

    /**
     * @param domicilioEnEdicion the domicilioEnEdicion to set
     */
    public void setDomicilioEnEdicion(Domicilio domicilioEnEdicion) {
        this.domicilioEnEdicion = domicilioEnEdicion;
    }

    /**
     * @return the hash
     */
    public String getHash() {
        return hash;
    }

    /**
     * @param hash the hash to set
     */
    public void setHash(String hash) {
        this.hash = hash;
    }

    /**
     * @return the actividadesEnEdicion
     */
    public HashMap<String,TbActEco> getActividadesEnEdicion() {
        return actividadesEnEdicion;
    }

    /**
     * @param actividadesEnEdicion the actividadesEnEdicion to set
     */
    public void setActividadesEnEdicion(HashMap<String,TbActEco> actividadesEnEdicion) {
        this.actividadesEnEdicion = actividadesEnEdicion;
    }

    /**
     * @return the representantesEnEdicion
     */
    public HashMap<String,RcRepresentante> getRepresentantesEnEdicion() {
        return representantesEnEdicion;
    }

    /**
     * @param representantesEnEdicion the representantesEnEdicion to set
     */
    public void setRepresentantesEnEdicion(HashMap<String,RcRepresentante> representantesEnEdicion) {
        this.representantesEnEdicion = representantesEnEdicion;
    }

    /**
     * @return the casaMatrizEnEdicion
     */
    public Domicilio getCasaMatrizEnEdicion() {
        return casaMatrizEnEdicion;
    }

    /**
     * @param casaMatrizEnEdicion the casaMatrizEnEdicion to set
     */
    public void setCasaMatrizEnEdicion(Domicilio casaMatrizEnEdicion) {
        this.casaMatrizEnEdicion = casaMatrizEnEdicion;
    }

    
    
	
}
